class UsersController < ApplicationController

  before_filter :login_required
  before_filter :admin_only, :except => [:index, :language, :change_language, :map]  
  before_filter :set_users_title
  rescue_from Exception, :with => :render_error

  def render_error(exception)
    logger.info "User logged : #{current_user.inspect}"
    log_error(exception)
    render :template => "/errors/error.html.erb"
  end
  
  def index
    data_for_view_users(true)
    @allow_login=true
    
  end
  
  def show_users_blocked
     data_for_view_users(false)
     @allow_login=false
     render :action => "index"
  end

  def delete
     user=User.find(params[:id])
     user.roles.clear
     User.delete(params[:id])
     #borrar relacion con roles
     redirect_to :action => "index"
  end


  def new
    @user = User.new
    @roles_map=nil
  end
  
  def set_user_and_rollback(user_map)
    set_user_and_map_roles(user_map)
    raise ActiveRecord::Rollback
  end

  def create
    logger.info "Creating a new user"
    transaction_end=true
    User.transaction do
      user_map=prepare_user(params[:user])
      roles=load_roles(params[Site.name],params[Country.name],params[Strategy.name])
      user_map["roles"]=roles
      
      # the user needs some role.
      if roles.empty? && user_map["is_admin"].to_i!=1
        message_t=_("The user can't be created, at least must have one role associated.\nPlease select the apropiated roles for this user")
        message= "The user can't be created, at least must have one role associated.\nPlease select the apropiated roles for this user"
        messages_error(message_t,message)
        transaction_end=false
        set_user_and_rollback(user_map)          
      end
      
      if not create_user(user_map,roles)
        transaction_end=false
        raise ActiveRecord::Rollback
      end

      if transaction_end
        if not create_report_response_for_all_roles(roles)
          transaction_end=false
          raise ActiveRecord::Rollback
        end
      end
    end
    if transaction_end
      redirect_to(:action => "index")
    else
      charge_roles_map(params[Site.name],params[Country.name],params[Strategy.name])
      render :action => "new"
    end
  end
  
  def language
    render :action => "language", :layout => false
    
  end
  
    def help_addtranslator
    render :action => "help_addtranslator", :layout => false
    
  end
  
  
  def create_report_response_for_all_roles(roles)
    
  end
  
  
  def edit
    redirect_to(:action => "index") if params[:id].blank?
    set_user_and_map_roles(params[:id])
  end
  
  def update
    logger.info "Updating user. User id:#{}"
    transaction_end=true
    User.transaction do
      user_map=prepare_user(params[:user],params[:id])
      user_map["id"]=params[:id]
      roles=load_roles(params[Site.name],params[Country.name],params[Strategy.name])
      user_map["roles"]=roles

      # the user needs some role.
      if roles.empty? && user_map["is_admin"].to_i!=1
        messages_error( _("The user can't be updated, at least must have one role associated.\nPlease select the apropiated roles for this user"),"The user can't be updated id #{params[:id]}")
        transaction_end=false
        set_user_and_rollback(user_map)
      end
        
      if not update_user(user_map,params[:id],roles)
        transaction_end=false
        raise ActiveRecord::Rollback  
      end

      if transaction_end
        if not create_report_response_for_all_roles(roles)
          transaction_end=false
          raise ActiveRecord::Rollback
        end
      end
    end
    if transaction_end
      redirect_to(:action => "index")
    else
      charge_roles_map(params[Site.name],params[Country.name],params[Strategy.name])
      render :action => "edit"
    end
  end
  
  def change_language
    if current_user.update_attribute(:preferred_language, params[:user][:preferred_language])
      redirect_to request.referer
    end
 
end

  def admin_lang
    @title = _('Admin Translations')
    @active_tab = :language
  end
  
  def map
    @title = _('Data Visualization')
    @active_tab = :map
   
  end
  
   def map_data_strategy
    current_report = ReportRequest.current
    var = " {\"type\":\"FeatureCollection\",\"features\":[" +"\n"
    Site.all.each do |site|
      coordinator = site.coordinator_role
      if (coordinator.nil? == false) 
        var << "{\"type\":\"Feature\",\"id\":4,\"geometry\":{\"type\":\"Point\",\"coordinates\":["
        var << site.longitude.to_s
        var << ", "
        var << site.latitude.to_s
        var << "]},\"properties\":{\"name\":\""
        var << site.city.to_s + "\","
        var << "\"Coordinator\":\""+ (coordinator.nil? == false).to_s+ "\","
        var << "\"Completeness\":\""
        report_response = coordinator.report_responses.select{|r|r.report_request = current_report}.first rescue nil
        var <<(((report_response.completed) * 100).to_i.to_s rescue "0")
        var << "\"," + "\"" 
        total_yes=(report_response.count_yes_answers.to_s rescue "0")
        var << "Yes\":\"" + total_yes
        total_no = (report_response.count_no_answers.to_s rescue "0")
        var << "\"," + "\"No\":\"" + total_no
        var << "\"," + "\"N/A\":\"" + (((report_response.report.questions.select{|q| q.available_for(coordinator)}.count rescue 0) - total_yes.to_i - total_no.to_i).to_s rescue "0")
        var << "\""
        Grouping.all.each do |g|
          yes_answ = (report_response.count_yes_answers_for_group(g).to_s rescue "0")
          var << ",\"" + g.tab_name.to_s + " Yes\":\"" + yes_answ
          no_answ = (report_response.count_no_answers_for_group(g).to_s rescue "0")
          var << "\",\"" + g.tab_name.to_s + " No\":\""  + no_answ
          var << "\",\"" + g.tab_name.to_s + " N/A\":\""  + ((report_response.report.questions.select{|q| q.available_for(coordinator) && q.grouping == g}.count rescue 0) - yes_answ.to_i - no_answ.to_i ).to_s rescue "0" 
          var << "\""
        end
        var << "}},\n"
      end
    end
    var << "]}"
    render :text => var, :layout => false
  end
  
  def map_data
    var = " {\"type\":\"FeatureCollection\",\"features\":[" +"\n"
    ReportRequest.current.get_xb_responses_grouped_by_site.each do |rr|
      var << "{\"type\":\"Feature\",\"id\":4,\"geometry\":{\"type\":\"Point\",\"coordinates\":["
      var << rr.first.longitude.to_s
      var << ", "
      var << rr.first.latitude.to_s
      var << "]},\"properties\":{\"name\":\""
      var << rr.first.city.to_s + "\",\"Completeness\":\""
      var <<((rr.last.first.completed) * 100).to_i.to_s
      var << "\"," + "\"Yes\":\"" + rr.last.first.count_yes_answers.to_s
      var << "\"," + "\"No\":\"" + rr.last.first.count_no_answers.to_s
      var << "\"," + "\"N/A\":\"" + (rr.last.first.report.questions.select{|q| q.available_for(rr.first.coordinator_role)}.count - rr.last.first.count_yes_answers - rr.last.first.count_no_answers).to_s
      var << "\"}}," +"\n"
    end
    var << "]}" 
    
     render :text => var, :layout => false
  end
  

  private
  
  def charge_roles_map(sites,countries,strategies)
    @roles_map=Hash.new
    @roles_map[Site.name]=sites
    @roles_map[Country.name]=countries
    @roles_map[Strategy.name]=strategies
  end
  
  def create_report_response_for_all_roles(roles)
    Role.all.each do |role|
      ReportRequest.all.each{|r_req|
        repo_responses=ReportResponse.find_all_by_owner_role_id_and_report_request_id(role.id, r_req)
        if repo_responses.length == 0
          begin
            ReportResponse.create!(:is_submitted =>false, :report_request => r_req, :owner_role => role)
          rescue 
            return false
          end  
        end  
      }
    end
    return true
  end
  
  def index_load_admin_data(can_login)
    row_data=Array.new
    users=User.find(:all, :conditions => {:is_admin => true}).sort{ |u1, u2| u1.country.name <=> u2.country.name }
    users.each{|user|
      if user.allow_login == can_login
        last_login=""
        last_login=user.last_login.strftime("%x") unless user.last_login.nil?
        row_data+=[[user.country.name, user.city, user.name, user.email, user.phone, last_login,user.share_one_role(current_user),user.id]]
      end
    }
     return row_data
  end
  
  def index_load_xb_data(roles, can_login)
    if roles.nil? || roles.empty?
      return nil
    end
    
    site_array=Array.new
    roles.each{|role|
      row_data=Array.new
      role.users.each {|user|
        if user.allow_login == can_login
          last_login=""
          last_login=user.last_login.strftime("%x") unless user.last_login.nil?
          modify_one_report=check_if_user_modify_reports(user.id)
          row_data+=[[user.country.name, user.city, user.name, user.email,user.phone,last_login,user.share_one_role(current_user),user.id,!modify_one_report]]
        end        
      }
      if not row_data.empty?
        row_array=["#{role.coordinated.cross_borders.map {|xb| "XB-#{xb.number}"}.join(', ')}  #{role.coordinated.name}-#{role.coordinated.matching_names}"]
        row_array+=[row_data.sort{|r1,r2| r1[0] <=> r2[0]}]
        site_array+=[row_array]
      end
    }
    return site_array 
  end
  
  def index_load_strategy_data(can_login)
    roles = Role.find_all_by_coordinated_type(Strategy.name)
    if roles.nil? || roles.empty?
      return nil
    end
    row_data=Array.new
    roles.each{|role|
      role.users.each {|user|
        if user.allow_login == can_login
          last_login=""
          last_login=user.last_login.strftime("%x") unless user.last_login.nil?
          modify_one_report=check_if_user_modify_reports(user.id)
          row_data+=[[user.country.name, user.city, user.name, user.email, role.coordinated.short_name ,user.phone,last_login,user.share_one_role(current_user),user.id,!modify_one_report]]
        end  
      }         
    }
    return row_data.sort {|r1,r2| r1[0] <=> r2[0]}
  end
  
  def index_load_country_data(roles,can_login)
    if roles.nil? || roles.empty?
      return nil
    end
    row_data=Array.new
    roles.each{|role|
      role.users.each {|user|
        if user.allow_login == can_login
          last_login=""
          last_login=user.last_login.strftime("%x") unless user.last_login.nil?
          modify_one_report=check_if_user_modify_reports(user.id)
          row_data+=[[user.country.name, user.city, user.name, user.email, user.phone,last_login,user.share_one_role(current_user),user.id,!modify_one_report]]
        end  
      }         
    }
    return row_data.sort {|r1,r2| r1[0] <=> r2[0]}
  end

  
  def set_user_and_map_roles(user)
    if user.instance_of? String
      @user=User.find user.to_i
    else
      @user=User.new user
      @user.id=user["id"]
    end
    
    @roles_map=Hash.new
    @user.roles.each{|role|
      if @roles_map[role.coordinated_type].nil?
        @roles_map[role.coordinated_type]=Array.new
      end  
      @roles_map[role.coordinated_type].push(role.coordinated.id)
    }
  end
  
  def set_users_title
    @title = _('Authorized User List')
    @active_tab = :users
  end
  
   def messages(message,log)
    logger.info log
    flash[:notice] = message 
  end
  
  def messages_error(message,log)
    logger.info log
    flash[:error_notice] = message
  end
  
  def update_user(user,id,roles)
    user["roles"]=Array.new
    @user= User.update(id, user) 
    if @user.valid?
      @user.roles.clear
      if roles.empty?
          @user.save 
          if !@user.valid?
            messages_error( _('User was not updated'), "User was not updated. User:#{@user}")
            return false    
          end
      end

      roles.each{|role|
        @user.roles.push(role)
      }
      messages( _('User updated'), "User updated succesfully. User:#{@user}")
      return true
    else
      messages_error( _('User was not updated'), "User was not updated. User:#{@user}")
      return false
    end
  end
  
  def create_user(user,roles)
    user["roles"]=Array.new
    @user= User.create(user) 
    if @user.valid?
      @user.roles.clear
      roles.each{|role|
        @user.roles.push(role)
      }
      messages( _('User created successfully'),"User created succesfully. User:#{@user}")
      return true
    else
      messages_error( _('User was not created'), "User was not created. User:#{@user}")
      return false
    end
  end
  
  def load_roles(site_roles,country_roles,strategy_roles)
    roles=Array.new
    if not site_roles.nil?
      site_roles.each { |type_id|
        id=type_id.to_i
        role=Role.find_by_coordinated_id_and_coordinated_type(id, Site.name)
        if role.nil?
          site=Site.find(id)
          role=Role.create!(:coordinated => site)
        end
        roles.push(role)
      }
    end
    if not country_roles.nil?
      country_roles.each { |type_id|
        id=type_id.to_i
        if not id==-1
          role=Role.find_by_coordinated_id_and_coordinated_type(id, Country.name)
          if role.nil?
            country=Country.find(id)
            role=Role.create!(:coordinated => country)
           end
          roles.push(role)
        end
      }
    end
    if not strategy_roles.nil?
      strategy_roles.each { |type_id|
        id=type_id.to_i
        role=Role.find_by_coordinated_id_and_coordinated_type(id, Strategy.name)
        if role.nil?
          strategy=Strategy.find(id)
          role=Role.create!(:coordinated => strategy)
        end
        roles.push(role)
      }
    end
    return roles
  end
  
  def prepare_user(user,id=nil)
    user_map=user
    user_map["id"]=id unless id.nil?
    user_map.delete_if {|key, value| (key == ("password")  && value=="")}
    user_map.delete_if {|key, value| (key == ("password_confirmation")  && value=="")}
    return user_map
  end
  
  def data_for_view_users(can_login)
      if current_user.is_admin?
      sites = Role.find_all_by_coordinated_type(Site.name).sort {|s1,s2| s1.coordinated.cross_borders.map(&:number).min <=> s2.coordinated.cross_borders.map(&:number).min}
      @sites=index_load_xb_data(sites,can_login)
      countries = Role.find_all_by_coordinated_type(Country.name,can_login)
      @countries=index_load_country_data(countries,can_login)
      @strategies=index_load_strategy_data(can_login)
      @admins=index_load_admin_data(can_login)
    else
      current_user.roles.select(&:is_country_coordinator).each do |role|
        country = role.coordinated
        sites = []
        sites += Site.find_all_by_country_id(country.id).reject{ |s| s.coordinator_role.nil?}.map(&:coordinator_role)
      end
      @sites=index_load_xb_data(sites,can_login)
      current_user.roles.select(&:is_strategy_coordinator).each do |role|
        countries = []
        countries += Role.find_all_by_coordinated_type("Country")
      end
      @countries=index_load_country_data(countries,can_login)
    end 
 end

  def check_if_user_modify_reports(id)
    count = ReportEdit.count(:conditions => "user_id=" + id.to_s)
    if count > 0
      return true
    end
    return false
  end 
end